﻿#include "keyHook.hpp"
#include <cassert>
HINSTANCE g_hins=NULL;
HHOOK g_keyhook = NULL;
HWND g_host = NULL;
bool g_enable = false;
LRESULT CALLBACK LowLevelMouseProc(
	int nCode,
	WPARAM wParam,
	LPARAM lParam
) 
{


	
	return CallNextHookEx(g_keyhook, nCode, wParam, lParam);
}
int g_timer=0;
UINT_PTR IDEvent = 0;
VOID CALLBACK TimerProc(HWND  hwnd, UINT  uMsg, UINT_PTR idEvent, DWORD dwTime) {
	g_timer = 0;
	KillTimer(NULL, IDEvent);
	IDEvent = 0;
}


LRESULT CALLBACK LowLevelKeyboardProc(
	int	nCode,
	WPARAM wParam,
	LPARAM lParam
) 
{
	LRESULT ret;
	if (WM_KEYUP == wParam ) {
		ret = CallNextHookEx(g_keyhook, nCode, wParam, lParam);
		KBDLLHOOKSTRUCT &p= *((PKBDLLHOOKSTRUCT)lParam);
		short lctl = GetAsyncKeyState(VK_LCONTROL);
		short rctl = GetAsyncKeyState(VK_RCONTROL);
		short _c = GetAsyncKeyState(0x43);
		short win = GetAsyncKeyState(VK_LWIN);
		if ((VK_LWIN == p.vkCode &&lctl) || (VK_LCONTROL == p.vkCode &&win))
		{
			g_enable = !g_enable;
			if (g_enable) Beep(3000, 200); else  Beep(1500, 200);
			return ret;
		}
		if ((VK_RCONTROL == p.vkCode &&win) || (VK_LWIN == p.vkCode&&rctl)) {
			PostMessage(g_host, WM_DESTROY, 0, 0);
			Beep(1500, 500);
			return ret;
		}
		if (!g_enable) return ret;
		if (((0x43 == p.vkCode) && lctl)||(VK_LCONTROL==p.vkCode && _c)) {
			if (g_timer>0)
				PostMessage(g_host, WM_DRAWCLIPBOARD, 0, 0);
			else {
				g_timer++;
				IDEvent=SetTimer(NULL, IDEvent, 500, TimerProc);
			}
		}
		return ret;
	}
	return CallNextHookEx(g_keyhook, nCode, wParam, lParam);
}

HOOK_API bool WINAPI startCatch(HWND pwnd)
{
	if (g_host != NULL || g_keyhook != NULL) return false;
	g_keyhook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,g_hins,0);
	if (g_keyhook != NULL) {
		g_host = pwnd;
		return true;
	}
	return false;
}
HOOK_API bool WINAPI stopCatch()
{
	if (UnhookWindowsHookEx(g_keyhook) == 0) return false;
	g_keyhook = NULL;
	g_host = NULL;
	return true;
}
bool APIENTRY DllMain(HMODULE hModule,
	DWORD reson,
	LPVOID lpReserved
)
{
	g_hins = (HINSTANCE)hModule;
	switch (reson)
	{
	case DLL_PROCESS_ATTACH:
		Beep(3000, 500);
		break;
	case DLL_PROCESS_DETACH:
		if (g_keyhook != NULL) {
			UnhookWindowsHookEx(g_keyhook);
		}
		break;
	}
	return true;
}
